package com.sys.group.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sys.group.entity.Menu;
import com.sys.group.entity.User;
import com.sys.group.entity.UserRole;
import com.sys.group.mapper.UserMapper;
import com.sys.group.mapper.UserRoleMapper;
import com.sys.group.service.IMenuService;
import com.sys.group.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.sys.common.utils.Time.TimetoStr;
import static com.sys.common.utils.Time.getNowTime;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author gyf
 * @since 2023-05-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private IMenuService menuService;

    @Override
    public Map<String, Object> login(User user) {
        // 根据用户名和查询
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
        User loginUser = this.baseMapper.selectOne(wrapper);
        // 结果不为空，并且密码和传入密码匹配，则生成token，并将用户信息存入redis
        if (loginUser != null && passwordEncoder.matches(user.getPassword(), loginUser.getPassword())) {
            // uuid
            String key = "user::" + UUID.randomUUID();
//            System.out.println("key: " + key);
            // 不存密码
            loginUser.setPassword(null);
            // 更新mysql
            loginUser.setLastLogin(getNowTime());
            this.baseMapper.updateLastLogin(loginUser);
            // 存入redis
            redisTemplate.opsForValue().set(key, loginUser, 24, TimeUnit.HOURS);

            // 返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("token", key);

            return data;
        }

        return null;
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        // 根据token从redis中获取用户信息
        Object obj = redisTemplate.opsForValue().get(token);
        // redis中存的数据是经过序列化处理的，取出来读取前需要进行反序列化
        if (obj != null) {
            // 调用fastjson2中方法，将传入字符串反序列化为所需目前类型
            User loginUser = JSON.parseObject(JSON.toJSONString(obj), User.class);

            Map<String, Object> data = new HashMap<>();
            // id
            data.put("id", loginUser.getId());
            // username
            data.put("name", loginUser.getUsername());
            // 角色
            List<String> roleList = this.baseMapper.getRoleNameByUserId(loginUser.getId());
            data.put("roles", roleList);
            List<Integer> roleIdList = this.baseMapper.getRoleIdByUserId(loginUser.getId());
            data.put("roleIdList", roleIdList);
            // avator
            data.put("avatar", loginUser.getAvator());
            // 添加其他需获取的数据
            data.put("email", loginUser.getEmail());
            data.put("phone", loginUser.getPhone());
            data.put("register", TimetoStr(loginUser.getRegisterTime()));
            data.put("lastLogin", TimetoStr(loginUser.getLastLogin()));
            data.put("status", loginUser.getStatus());

            // 权限列表
            List<Menu> menuList = menuService.getMenuListByUserId(loginUser.getId());
            // 去重
            Set<Menu> menuSet = new LinkedHashSet<>(menuList);
            menuList = new ArrayList<>(menuSet);

            // children去重
            removeDb(menuList);

            System.out.println("menuList: " + menuList);
            data.put("menuList", menuList);

            return data;
        }
        return null;
    }

    private void removeDb(List<Menu> menuList) {
        if (menuList != null) {
            for (Menu menu : menuList) {
                if (menu.getChildren() != null) {
                    Set<Menu> menuSet = new LinkedHashSet<>(menu.getChildren());
                    menu.setChildren(new ArrayList<>(menuSet));
                }
                removeDb(menu.getChildren());
            }
        }

    }

    @Override
    public void logout(String token) {
        // 根据token删除redis中数据
        redisTemplate.delete(token);
    }

    @Override
    @Transactional
    public void addUser(User user) {
        // 补全用户属性
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setRegisterTime(getNowTime());
        if (user.getStatus() == null) user.setStatus(1);
        user.setAvator("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        user.setDeleted(0);
        // 写入用户表
        this.baseMapper.insert(user);

        // 写入用户角色表
        List<Integer> roleIdList = user.getRoleIdList();
        if (roleIdList != null) {
            for (Integer roleId : roleIdList) {
                userRoleMapper.insert(new UserRole(user.getId(), roleId));
            }
        }

    }

    @Override
    public User getUserById(Integer id) {
        // 查用户表
        User user = this.baseMapper.selectById(id);

        // 查用户角色表
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper();
        wrapper.eq(UserRole::getUid, id);
        List<UserRole> userRolesList =  userRoleMapper.selectList(wrapper);
        List<Integer> roleIdList = new ArrayList<>();
        for (UserRole userRole : userRolesList) {
            roleIdList.add(userRole.getRid());
        }
        user.setRoleIdList(roleIdList);

        // 返回
        return user;
    }

    @Override
    public void updateUser(User user) {
        // 更新用户表
        this.baseMapper.updateById(user);

        // 删除原有用户角色
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUid, user.getId());
        userRoleMapper.delete(wrapper);

        // 更新用户角色
        List<Integer> roleIdList = user.getRoleIdList();
        if (roleIdList != null) {
            for (Integer roleId : roleIdList) {
                userRoleMapper.insert(new UserRole(user.getId(), roleId));
            }
        }
    }

    @Override
    public void deleteUserById(Integer id) {
        // 删除用户表
        this.baseMapper.deleteById(id);

        // 删除用户角色表
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUid, id);
        userRoleMapper.delete(wrapper);
    }

    @Override
    public void updateMyInfo(User user) {
        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        // 更新用户表
        this.baseMapper.updateMyInfo(user);
    }


}
